package com.educatioin.manage.web.system.service;

import com.educatioin.commons.exceptions.ServiceException;
import com.educatioin.manage.web.productorder.response.ListOrderRsp;
import com.educatioin.manage.web.schoolgradeclass.po.SchoolGradeClassPo;
import com.educatioin.manage.web.schoolgradeclass.service.SchoolGradeClassService;
import com.educatioin.manage.web.system.po.CustomerPo;
import com.educatioin.manage.web.system.repository.CustomerRepository;
import com.educatioin.manage.web.system.request.CreateCustomerReq;
import com.educatioin.manage.web.system.request.ListCustomerReq;
import com.educatioin.manage.web.system.request.ModifyCustomerReq;
import com.educatioin.manage.web.system.response.ListCustomerRsp;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Created by caizh on 18-5-2.
 */
@Service
public class CustomerService {

    @Resource
    private CustomerRepository customerRepository;

    @Resource
    private SchoolGradeClassService schoolGradeClassService;

    public CustomerRepository getCustomerRepository() {
        return customerRepository;
    }

    public ListCustomerRsp list(ListCustomerReq req) {
        if(null == req.getPage() || req.getPage() <= 0
                || null == req.getLimit() || req.getLimit() <= 0){
            throw new ServiceException("分页查询错误！");
        }

        int page = req.getPage();
        if(page > 0) {
            page = page -1;
        }

        Sort sort = new Sort(Sort.Direction.DESC, "id");
        Pageable pageRequest = new PageRequest(page, req.getLimit(), sort);

        Page<CustomerPo> retPage = customerRepository.findAll((root, query, cb) -> {
            List<Predicate> predicates = Lists.newArrayList();
            if(StringUtils.isNoneBlank(req.getCode())) {
                predicates.add(cb.and(cb.equal(root.get("code"), req.getCode())));
            }
            if(StringUtils.isNoneBlank(req.getName())) {
                predicates.add(cb.and(cb.equal(root.get("name"), req.getName())));
            }
            if(StringUtils.isNoneBlank(req.getPhone())) {
                predicates.add(cb.and(cb.equal(root.get("phone"), req.getPhone())));
            }
            if(req.getEnabled() != null) {
                predicates.add(cb.and(cb.equal(root.get("enabled"), req.getEnabled())));
            }
            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        }, pageRequest);

        ListCustomerRsp rsp = new ListCustomerRsp();
        rsp.setCount((int) retPage.getTotalElements());
        if (CollectionUtils.isNotEmpty(retPage.getContent())) {
            Iterable<SchoolGradeClassPo> schoolList = schoolGradeClassService.getSchoolGradeClassRepository().findAll(
                    retPage.getContent().stream().map(CustomerPo::getSchoolGradeClassId).collect(Collectors.toList()));
            Map<Long, String> schoolMap = Maps.newHashMap();
            schoolList.forEach(s -> schoolMap.put(s.getId(), Joiner.on("/").join(s.getSchoolName(), s.getGrade(), s.getClazz())));
            retPage.getContent().forEach(c -> c.setSchoolGradeClassName(
                    Optional.ofNullable(schoolMap.get(c.getSchoolGradeClassId())).orElse("")));
        }
        rsp.setData(retPage.getContent());
        rsp.setReturnCode(ListOrderRsp.RETURN_SUCCESS_CODE);

        return rsp;
    }

    @Transactional(rollbackFor = Exception.class)
    public void modify(ModifyCustomerReq req) {
        CustomerPo c = customerRepository.findOne(req.getId());
        Optional.ofNullable(req.getCode()).ifPresent(c::setCode);
        Optional.ofNullable(req.getName()).ifPresent(c::setName);
        Optional.ofNullable(req.getEnabled()).ifPresent(c::setEnabled);
        Optional.ofNullable(req.getPhone()).ifPresent(c::setPhone);
        Optional.ofNullable(req.getPoint()).ifPresent(c::setPoint);
        Optional.ofNullable(req.getType()).ifPresent(c::setType);
        Optional.ofNullable(req.getSchoolGradeClassId()).ifPresent(c::setSchoolGradeClassId);

        c.setUpdateTime(System.currentTimeMillis());

        customerRepository.save(c);
    }

    @Transactional(rollbackFor = Exception.class)
    public void create(CreateCustomerReq req) {
        CustomerPo po = new CustomerPo();
        po.setPhone(req.getPhone());
        po.setCode(req.getCode());
        po.setEnabled(req.getEnabled());
        po.setName(req.getName());
        po.setPassword(getSHA256Str(req.getPassword()));
        po.setPoint(req.getPoint());
        po.setSchoolGradeClassId(req.getSchoolGradeClassId());
        po.setType(req.getType());
        po.setCreateTime(System.currentTimeMillis());

        customerRepository.save(po);
    }


    private String getSHA256Str(String str){
        MessageDigest messageDigest;
        String encdeStr = "";
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            byte[] hash = messageDigest.digest(str.getBytes("UTF-8"));
            encdeStr = Hex.encodeHexString(hash);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return encdeStr;
    }

    public CustomerPo findById(Long id) {
        return customerRepository.findOne(id);
    }
}
